'''Simple math operations module.

Verifies distance between two points or between a point and a line segment.'''

from math import hypot, fabs, atan2, radians, cos, sin
from pygame import draw, display

def average_color(A, wA, B, wB):
    d = wA+wB
    return ((A[0]*wA+B[0]*wB)/d, (A[1]*wA+B[1]*wB)/d, (A[2]*wA+B[2]*wB)/d)

def dot_product(A, B, C):
    '''Computes the dot product AB . BC'''
    AB = (B[0]-A[0], B[1]-A[1])
    BC = (C[0]-B[0], C[1]-B[1])
    return AB[0]*BC[0] + AB[1]*BC[1]

def cross_product(A, B, C):
    '''Computes the cross product AB x AC'''
    AB = (B[0]-A[0], B[1]-A[1])
    BC = (C[0]-B[0], C[1]-B[1])
    return AB[0]*BC[1] - AB[1]*BC[0]

def point_point_distance(A, B):
    '''Computes the distance between two points'''
    return hypot(A[0]-B[0], A[1]-B[1])

def line_point_distance(A, B, P):
    '''Computes the distance from the line formed by AB to the point P'''
    return fabs(cross_product(A, B, P) / hypot(A, B))

def line_segment_point_distance(A, B, P):
    '''Computes the distance from the line segment AB to the point P'''
    if dot_product(A, B, P) > 0:
        return point_point_distance(B, P)
    if dot_product(B, A, P) > 0:
        return point_point_distance(A, P)
    return fabs(cross_product(A, B, P) / point_point_distance(A, B))

def push_back(A, B, P, d):
    '''Returns the position of P if it was "pushed back" by 'd' units from the
    line AB'''
    angle = atan2(B[1]-A[1], B[0]-A[0]) + radians(90)
    return (P[0]-d*cos(angle), P[1]-d*sin(angle))

def reflect_angle(A, B, angle):
    '''Reflects the given angle relative to the line segment AB.'''
    line_angle = atan2(B[1]-A[1], B[0]-A[0])
    theta      = angle - line_angle
    return angle - 2*theta